package com.gitee.shigen.security.service;

import cn.hutool.core.util.StrUtil;
import com.gitee.shigen.security.common.Constants;
import com.gitee.shigen.security.mapper.UserMapper;
import com.gitee.shigen.security.request.PageRequest;
import com.gitee.shigen.security.util.SecurityUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * @author shigenfu
 * @date 2024/5/25 17:43
 */
@Slf4j
@Service
public class MonitorService {

    @Resource
    private StringRedisTemplate stringRedisTemplate;

    @Resource
    private UserMapper userMapper;

    /**
     * 在线用户分页列表
     *
     * @param pageRequest 分页参数
     * @return 在线用户分页列表
     */
    public List<String> onlineUser(PageRequest pageRequest) {
        List<String> rows = getKeysByPrefix(Constants.REDIS_JWT_KEY_PREFIX, pageRequest.getPageNum(), pageRequest.getPageSize());
        // 根据 redis 中键获取用户名列表
        List<String> usernameList = rows.stream().map(s -> StrUtil.subAfter(s, Constants.REDIS_JWT_KEY_PREFIX, true)).collect(Collectors.toList());
        return usernameList;
    }

    /**
     * 踢出在线用户
     *
     * @param names 用户名列表
     */
    public void kickOut(List<String> names) {
        // 清除 Redis 中的 JWT 信息
        List<String> redisKeys = names.parallelStream().map(s -> Constants.REDIS_JWT_KEY_PREFIX + s).collect(Collectors.toList());
        stringRedisTemplate.delete(redisKeys);

        // 获取当前用户名
        String currentUsername = SecurityUtil.getCurrentUsername();
        names.parallelStream().forEach(name -> {
            // TODO: 通知被踢出的用户已被当前登录用户踢出，
            log.debug("用户【{}】被用户【{}】手动下线！", name, currentUsername);
        });
    }


    /**
     * 分页获取符合特定前缀的键
     *
     * @param prefix     前缀
     * @param pageNumber 页码
     * @param pageSize   每页数量
     * @return 符合特定前缀的键
     */

    public List<String> getKeysByPrefix(String prefix, int pageNumber, int pageSize) {
        if (StrUtil.isEmpty(prefix)) {
            return Collections.emptyList();
        }
        return Objects.requireNonNull(stringRedisTemplate.keys(prefix + "*"))
                .stream()
                .skip((long) (pageNumber - 1) * pageSize)
                .limit(pageSize)
                .collect(Collectors.toList());
    }
}
